48. 创建序列和数据框

本章概要

  • 学习材料:有名称索引的字典、二维数组和日期索引。
  • 本章任务:运行 lst-series-dict-demolst-array-to-dataframelst-set-index,创建带标签Series/DataFrame。
  • 完成后你将得到:index/columns/dtypes、日期索引表和shape。
  • 自我检查:检查日期索引唯一单调且数组宽度等于列数;重复索引时先检查原因。
  • 拓展练习:把结构创建拓展应用到长三角公司月度表。

本章学习目标

  • 理解Pandas两种核心数据结构:SeriesDataFrame
  • 掌握多种创建 Series 的方法(列表、字典、数组)
  • 掌握多种创建 DataFrame 的方法(字典、数组、嵌套列表)
  • 学会设置 DataFrame 的行索引
  • 理解数据结构之间的相互转换

从NumPy到Pandas:为什么需要Pandas?

NumPy数组在数据分析中存在三个关键限制:

  • 缺乏标签:只能通过整数位置访问,无法使用股票代码、日期等标签
  • 数据类型单一:所有元素必须是相同类型
  • 缺失值处理:使用NaN表示缺失值,但处理不够灵活

Pandas通过 SeriesDataFrame 完美解决了这些问题。

Pandas两种核心数据结构对比

特性 Series DataFrame
维度 一维 二维
类比 带标签的数组 带标签的表格
索引 必须有索引 行索引 + 列名
金融应用 单只股票价格序列 多只股票多指标数据表

什么是Series?

Series是Pandas的 一维数据结构,可以理解为「带标签的数组」。

  • 索引(index):每个数据点的标签
  • 值(values):实际存储的数据
  • 名称(name):Series对象的标识(可选)
  • 数据类型(dtype):值的类型(int64、float64等)

创建Series:三种常用方法

Listing 1: 创建Pandas Series的三种方法
展开实现代码
import pandas as pd
import numpy as np

# 方法1:从Python列表创建
s1 = pd.Series([10, 20, 30, 40, 50])

# 方法2:从字典创建(键自动成为索引)
s2 = pd.Series({
    '贵州茅台': 1850,
    '五粮液': 220,
    '招商银行': 45
}, name='股价')

# 方法3:从NumPy数组创建
s3 = pd.Series(np.random.randn(5))

print('Series 1 (从列表创建):')
print(s1)
Series 1 (从列表创建):
0    10
1    20
2    30
3    40
4    50
dtype: int64

从字典创建Series的优势

Listing 2: 从字典创建Series示例
展开实现代码
import pandas as pd

s2 = pd.Series({
    '贵州茅台': 1850,
    '五粮液': 220,
    '招商银行': 45
}, name='股价')

print('Series 2 (从字典创建):')
print(s2)
print(f'索引: {s2.index.tolist()}')
Series 2 (从字典创建):
贵州茅台    1850
五粮液      220
招商银行      45
Name: 股价, dtype: int64
索引: ['贵州茅台', '五粮液', '招商银行']
  • 索引自动设置为字典的键,无需手动指定
  • 适合表示有标签的数据(如股票名称→价格的映射)

什么是DataFrame?

DataFrame是Pandas的 二维数据结构,类似于Excel表格。

  • 是金融分析中 最常用 的数据结构
  • 每一列可以是不同的数据类型
  • 有行索引和列名两种标签

从字典创建DataFrame

Listing 3: 创建Pandas DataFrame
import pandas as pd

data = {
    '股票代码': ['600519.SH', '000858.SZ', '600036.SH'],
    '股票名称': ['贵州茅台', '五粮液', '招商银行'],
    '股价': [1850.0, 220.5, 45.2],
    '涨跌幅': [0.05, -0.02, 0.03]
}

df = pd.DataFrame(data)
print('DataFrame内容:')
print(df)
DataFrame内容:
        股票代码  股票名称      股价   涨跌幅
0  600519.SH  贵州茅台  1850.0  0.05
1  000858.SZ   五粮液   220.5 -0.02
2  600036.SH  招商银行    45.2  0.03

查看DataFrame的基本属性

Listing 4: DataFrame基本属性
展开实现代码
import pandas as pd

data = {
    '股票代码': ['600519.SH', '000858.SZ', '600036.SH'],
    '股票名称': ['贵州茅台', '五粮液', '招商银行'],
    '股价': [1850.0, 220.5, 45.2],
    '涨跌幅': [0.05, -0.02, 0.03]
}
df = pd.DataFrame(data)

print(f'DataFrame形状: {df.shape}')
print(f'列名列表: {df.columns.tolist()}')
DataFrame形状: (3, 4)
列名列表: ['股票代码', '股票名称', '股价', '涨跌幅']
  • shape 返回 (行数, 列数)
  • columns 获取所有列名

从NumPy数组创建DataFrame

Listing 5: 从NumPy数组创建DataFrame
展开实现代码
import numpy as np
import pandas as pd

arr = np.random.randn(5, 3)

df_random = pd.DataFrame(
    arr,
    columns=['特征1', '特征2', '特征3'],
    index=['样本1', '样本2', '样本3', '样本4', '样本5']
)

print('从NumPy数组创建的DataFrame:')
print(df_random)
从NumPy数组创建的DataFrame:
          特征1       特征2       特征3
样本1 -0.176680  0.777577 -0.159483
样本2 -0.096581  0.078718  1.605183
样本3 -0.704786 -1.944902 -0.645645
样本4  0.440582  0.351067  1.121835
样本5 -3.000069 -0.359660  0.005483
  • 适用于科学计算和金融建模产生的数据
  • 通过 columnsindex 参数添加有意义的标签

从嵌套列表创建DataFrame

Listing 6: 从列表的列表创建DataFrame
展开实现代码
import pandas as pd

data_list = [
    ['贵州茅台', 1850.0, 0.05],
    ['五粮液', 220.5, -0.02],
    ['招商银行', 45.2, 0.03]
]

df_from_list = pd.DataFrame(
    data_list,
    columns=['名称', '价格', '涨跌幅']
)

print('从列表的列表创建的DataFrame:')
print(df_from_list)
从列表的列表创建的DataFrame:
     名称      价格   涨跌幅
0  贵州茅台  1850.0  0.05
1   五粮液   220.5 -0.02
2  招商银行    45.2  0.03
  • 适用于从CSV或API获取的数据
  • 每个子列表对应一行数据

设置DataFrame的行索引

Listing 7: 设置DataFrame的行索引
展开实现代码
import pandas as pd

df = pd.DataFrame({
    '价格': [10, 20, 30, 40, 50],
    '销量': [100, 200, 150, 300, 250]
})

dates = pd.date_range('2024-01-01', periods=5)
df_indexed = df.set_index(dates)

print('带日期索引的DataFrame:')
print(df_indexed)
带日期索引的DataFrame:
            价格   销量
2024-01-01  10  100
2024-01-02  20  200
2024-01-03  30  150
2024-01-04  40  300
2024-01-05  50  250
  • pd.date_range() 生成日期序列
  • set_index() 将日期设置为行索引

使用日期索引的好处

设置日期索引后,可以更方便地进行时间序列操作:

  • df.loc['2024-01-01']:获取特定日期的数据
  • df.loc['2024-01-01':'2024-01-03']:获取日期范围内的数据
  • 支持按月、按季度等进行重采样聚合

比使用整数位置(iloc)更直观、更不容易出错。

本章小结

创建方式 适用场景
列表 → Series 简单一维数值数据
字典 → Series 有标签的键值对数据
字典 → DataFrame 列数据组织形式
数组 → DataFrame 科学计算/建模结果
嵌套列表 → DataFrame CSV/API获取的行数据

运行前预测|平台任务解答代码

  • 输入预测:运行前先写出 value_guotaidateseries_guotaidata 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。
  • 结果预测:不展开答案,先预测将得到array_3fund 的结果;同时写出方向、数量级或表格/图形结构。
  • 完成要求:能独立说明本任务从输入到“平台任务解答代码”结果的关键步骤,原样录入平台代码并得到可核对的运行结果。

⭐ 平台任务解答代码

展开完整代码(投影默认折叠)
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#任务一
import numpy as np
import pandas as pd  # 导入Pandas数据分析库

value_guotai = np.array([1.5284,1.4596,1.3745,1.4034,1.3935,1.39,1.412,1.4164]) #国泰金鑫股票基金2024年8月1日至8日净值数据的数组
date = np.array(["2024-08-01","2024-08-02","2024-08-05","2024-08-06","2024-08-07","2024-08-08","2024-08-09","2024-08-12"]) #交易日数组

series_guotai = pd.Series(data=value_guotai,index=date) #创建序列
print(type(series_guotai))  #查看变量的数据结构

data=[1.4596,1.001,0.897,2.051,1.7385];index=["国泰金鑫","中海医疗","华夏优势","富国城镇","上投摩根"] #创建8月2日基金净值的数组

value_0403 = pd.Series(data,index)  # 创建Series序列value_0403
print(type(value_0403))  # 输出数据类型


#任务二
import numpy as np
import pandas as pd  # 导入Pandas数据分析库

date = np.array(["2024-08-01","2024-08-02","2024-08-05","2024-08-06","2024-08-07","2024-08-08","2024-08-09","2024-08-12"]) #交易日数组

name = np.array(["国泰金鑫","中海医疗","华夏优势","富国城镇","上投摩根"])  #基金名称的数组并且用基金简称

data_3fund_array = np.array([[1.01,0.8918,2.038],[0.995,0.8833,2.025],[1.002,0.8735,2.032]]) #3只基金在2024年8月8日至12日净值的数组

data_3fund = pd.DataFrame(data=data_3fund_array,index=date[5:],columns=name[1:4]) #转成一个数据框

print(type(data_3fund))  # 输出数据类型

#任务三
import numpy as np
import pandas as pd  # 导入Pandas数据分析库

date = np.array(["2024-08-01","2024-08-02","2024-08-05","2024-08-06","2024-08-07","2024-08-08","2024-08-09","2024-08-12"]) #交易日数组

name = np.array(["国泰金鑫","中海医疗","华夏优势","富国城镇","上投摩根"])  # 创建NumPy数组name

# 创建NumPy数组value_total
value_total = np.array([[1.5284,0.991,0.9122,2.069,1.7742],[1.4596,1.001,0.897,2.051,1.7385],[1.3745,1,0.8786,2.023,1.6843],[1.4034,1.013,0.8944,2.027,1.6917],

[1.3935,1.007,0.8944,2.031,1.6957],[1.39,1.01,0.8918,2.038,1.6955],[1.412,0.995,0.8833,2.025,1.6938],[1.6938,1.002,0.8735,2.032,1.6899]]) #创建数组

data_total = pd.DataFrame(data=value_total,index=date,columns=name)  #转为数据框

print(data_total)  # 输出数据数据

#任务四
import numpy as np

import pandas as pd  # 导入Pandas数据分析库

value_guotai = np.array([1.5284,1.4596,1.3745,1.4034,1.3935,1.39,1.412,1.4164]) #国泰金鑫股票基金2024年8月1日至8日净值数据的数组

date = np.array(["2024-08-01","2024-08-02","2024-08-05","2024-08-06","2024-08-07","2024-08-08","2024-08-09","2024-08-12"]) #交易日数组

series_guotai = pd.Series(data=value_guotai,index=date)  # 创建Series序列series_guotai

data=[1.4596,1.001,0.897,2.051,1.7385];index=["国泰金鑫","中海医疗","华夏优势","富国城镇","上投摩根"] #创建8月2日基金净值的数组

value_0403 = pd.Series(data,index)  # 创建Series序列value_0403

name = np.array(["国泰金鑫","中海医疗","华夏优势","富国城镇","上投摩根"])  #基金名称的数组并且用基金简称

data_3fund_array =  np.array([[1.01,0.8918,2.038],[0.995,0.8833,2.025],[1.002,0.8735,2.032]])#3只基金在2024年8月8日至12日净值的数组

data_3fund = pd.DataFrame(data=data_3fund_array,index=date[5:],columns=name[1:4])  # 创建数据框data_3fund


list_guotai = list(series_guotai)#国泰金鑫8与1日到12日净值数据的序列转为列表

array_0403 = np.array(value_0403) #8月2日5只基金净值的序列转为数组

array_3fund = data_3fund.values  #8月8日到12日3只基金净值的数据框变为数组
print(array_3fund)  # 输出基金数据

任务复盘|平台任务解答代码

运行后核对:核对 value_guotaidateseries_guotaidata 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。

拓展练习:把输入表替换为本地中国上市公司数据的同结构子集;指出必须保持的字段、数据类型和质量检查。

随堂练习

  • 问题 1|需要准备哪些数据?:有名称索引的字典、二维数组和日期索引。
  • 问题 2|需要完成哪些操作?:运行 lst-series-dict-demolst-array-to-dataframelst-set-index,创建带标签Series/DataFrame。
  • 问题 3|应得到哪些结果?:index/columns/dtypes、日期索引表和shape。
  • 问题 4|怎样确认结果可靠?:检查日期索引唯一单调且数组宽度等于列数;重复索引时先检查原因。
  • 问题 5|换一个情境,怎样继续应用?:把结构创建拓展应用到长三角公司月度表。
  • 作答提示:请依次写清所用数据、分析过程、所得结果、核对方法和拓展思考。课程所需数据见前言中的下载入口;教学平台固定题按页面说明完成。

教师参考解答|答案与说明 1

  • 所用数据与字段date:str, code:str, close:float;日期唯一且按升序。

教师参考解答|代码 1

展开代码(代码区可独立滚动)
import pandas as pd  # 导入表格工具以构造、对齐和核对数据
raw={'date':['2025-01-02','2025-01-03'],'code':['600018.SH']*2,'close':[5.8,5.9]}  # 声明建表所需日期、代码与收盘价字段
frame=pd.DataFrame(raw)  # 声明建表所需日期、代码与收盘价字段
frame['date']=pd.to_datetime(frame['date'])  # 构造带业务字段的数据框输入
frame=frame.set_index('date').sort_index()  # 构造带业务字段的数据框输入
close=frame['close']  # 构造带业务字段的数据框输入
assert isinstance(close,pd.Series) and frame.index.is_monotonic_increasing  # 构造带业务字段的数据框输入
assert not frame.index.has_duplicates and close.dtype.kind=='f'  # 构造带业务字段的数据框输入
print(frame,frame.dtypes)  # 构造带业务字段的数据框输入

教师参考解答|答案与说明 2

  • 解释答案:Series 是带索引的一维序列,DataFrame 是共享行索引的列集合;日期、代码和数值类型必须在建表后显式校验。
  • 拓展应用答案:拓展应用到两只证券的收盘表时,扩展代码列并设置日期索引,检查索引有序无重复、close 为浮点且 Series 与 DataFrame 选择一致。
  • 参考结果:2×2 DataFrame、DatetimeIndex和字段类型。另行核对:用 frame.to_dict('list') 与原输入逐字段核对。
  • 常见错误:日期保留字符串;重复索引不检查;Series/DataFrame维度混淆。